﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Threading;

namespace DeepEarth.Core.Collections
{
	public class AtomicObservableCollection<T> : ObservableCollection<T>
	{
		private int _counter;
		private sealed class CollectionMonitor : IDisposable
		{
			private Action _disposeAction;
			public CollectionMonitor(Action disposeAction)
			{
				_disposeAction = disposeAction;
			}

			public void Dispose()
			{
				var action = Interlocked.Exchange(ref _disposeAction, null);
				if (action != null) action();
			}
		}

		public AtomicObservableCollection()
		{
		}

		public AtomicObservableCollection(IEnumerable<T> items)
#if !WINDOWS_PHONE
			: base(items) { }
#elif WINDOWS_PHONE
		{
			if (items == null) return;
			foreach(var item in items) Add(item);
		}
#endif

		public IDisposable GetAtomicOperation()
		{
			Interlocked.Increment(ref _counter);
			return new CollectionMonitor(DecrementCounter);
		}

		private void DecrementCounter()
		{
			var count = Interlocked.Decrement(ref _counter);
			if (count == 0)
				base.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
		}

		public bool IsInAtomicOperation { get { return _counter > 0; } }

		protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
		{
			if (IsInAtomicOperation) return;
			base.OnCollectionChanged(e);
		}
	}
}
